package com.tq.portal;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.Enumeration;

/**
 * 在应用启动完成之后打印 Banner。
 * <p>
 * 与默认的 {@code banner.txt} 不同，本类选择在启动完成后输出，
 * 主要是因为不喜欢默认 Banner 的打印时机。
 *
 * @author TqCoder
 * @since 2.0.0
 */
@Component
@Slf4j
public class BannerPrinter implements ApplicationListener<ApplicationReadyEvent> {

    private static final String BANNER = """
              \n
            ███████╗ ██████╗██╗  ██╗ ██████╗
            ██╔════╝██╔════╝██║  ██║██╔═══██╗
            █████╗  ██║     ███████║██║   ██║
            ██╔══╝  ██║     ██╔══██║██║   ██║
            ███████╗╚██████╗██║  ██║╚██████╔╝
            ╚══════╝ ╚═════╝╚═╝  ╚═╝ ╚═════╝
               ---- 有人视枯叶为华章，有人弃新枝如浊秧
            
            App running at:
                - Local:  http://localhost:%s%s                                                                                                                                                                                                                                                                               \s
                - Network: http://%s:%s%s
            """;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        Environment env = event.getApplicationContext().getEnvironment();
        String port = env.getProperty("server.port", "8080");
        String contextPath = env.getProperty("server.servlet.context-path", "");
        String host = resolveEthernetIp();
        String banner = String.format(BANNER, port, contextPath, host, port, contextPath);
        log.info(banner);
    }

    private static String resolveEthernetIp() {
        final String defaultIp = "127.0.0.1";
        try {
            return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
                    .filter(ni -> {
                        try {
                            return ni.isUp() && !ni.isLoopback() && !ni.isVirtual();
                        } catch (SocketException e) {
                            return false;
                        }
                    })
                    .flatMap(ni -> Collections.list(ni.getInetAddresses()).stream())
                    .filter(addr -> addr instanceof Inet4Address && !addr.isLoopbackAddress())
                    .map(InetAddress::getHostAddress)
                    .findFirst()
                    .orElse(defaultIp);
        } catch (SocketException e) {
            log.error("Failed to resolve ethernet IP", e);
            return defaultIp;
        }
    }

}
